Telegram Group & Telegram Channel
🐹 Задача для Go 1.21+: «Контекст отменён, но горутина продолжает работу»

📌 Актуально для: Go 1.21 и новее (введён `context.WithCancelCause`)
🎯 Цель: Понять, почему горутина не завершилась по отменённому контексту

📍 Ситуация:

Ты используешь контекст для управления жизненным циклом горутины. В Go 1.21 ты решил использовать context.WithCancelCause:


package main

import (
"context"
"fmt"
"time"
)

func main() {
ctx, cancel := context.WithCancelCause(context.Background())
go worker(ctx)

time.Sleep(1 * time.Second)
cancel(fmt.Errorf("manual stop"))

time.Sleep(2 * time.Second)
}

func worker(ctx context.Context) {
<-ctx.Done()
fmt.Println("Worker stopped:", context.Cause(ctx))
}


🔍 Ты ожидаешь, что горутина завершится и выведет:


Worker stopped: manual stop


Но вместо этого — программа завершилась без вывода. Почему?

🧩 Вопросы:

1. Почему worker не печатает "Worker stopped: ..."?
2. Что изменилось в context.WithCancelCause по сравнению с WithCancel?
3. Как безопасно читать причину отмены?
4. Как изменить worker, чтобы он корректно завершался?
5. Почему важно не блокироваться на `ctx.Done()`, если возможна гонка?

🛠 Решение:

🔸 В Go 1.21 есть `context.WithCancelCause`, который позволяет задавать причину отмены.
Но `context.Cause(ctx)` вернёт `nil`, **если ты используешь `context.WithCancel`**, либо, если `ctx.Done()` не был срабатывающим.

🔸 В этом коде `worker(ctx)` запускается и сразу блокируется на:

<-ctx.Done()


Но если отмена происходит **до** того, как `worker` успел начать слушать `ctx.Done()`, и ты используешь старую `WithCancel`, `context.Cause` вернёт `nil`.

🔸 **Правильный способ:**

Убедись, что `context.WithCancelCause` действительно используется и `ctx.Done()` слушается вовремя.

Для Go 1.21+ пример рабочий:



func worker(ctx context.Context) {
for {
select {
case <-ctx.Done():
fmt.Println("Worker stopped:", context.Cause(ctx))
return
case <-time.After(100 * time.Millisecond):
fmt.Println("Working...")
}
}
}



🔸 Альтернатива для старых версий Go (<1.21):


ctx, cancel := context.WithCancel(context.Background())
...
fmt.Println("Worker stopped:", ctx.Err()) // вместо Cause


📌 Вывод:
Начиная с Go 1.21, `context.WithCancelCause` даёт более точный контроль за причинами отмены. Но горутины всё равно должны явно проверять `ctx.Done()` через `select`, иначе отмена может пройти незаметно.



tg-me.com/golangtests/790
Create:
Last Update:

🐹 Задача для Go 1.21+: «Контекст отменён, но горутина продолжает работу»

📌 Актуально для: Go 1.21 и новее (введён `context.WithCancelCause`)
🎯 Цель: Понять, почему горутина не завершилась по отменённому контексту

📍 Ситуация:

Ты используешь контекст для управления жизненным циклом горутины. В Go 1.21 ты решил использовать context.WithCancelCause:


package main

import (
"context"
"fmt"
"time"
)

func main() {
ctx, cancel := context.WithCancelCause(context.Background())
go worker(ctx)

time.Sleep(1 * time.Second)
cancel(fmt.Errorf("manual stop"))

time.Sleep(2 * time.Second)
}

func worker(ctx context.Context) {
<-ctx.Done()
fmt.Println("Worker stopped:", context.Cause(ctx))
}


🔍 Ты ожидаешь, что горутина завершится и выведет:


Worker stopped: manual stop


Но вместо этого — программа завершилась без вывода. Почему?

🧩 Вопросы:

1. Почему worker не печатает "Worker stopped: ..."?
2. Что изменилось в context.WithCancelCause по сравнению с WithCancel?
3. Как безопасно читать причину отмены?
4. Как изменить worker, чтобы он корректно завершался?
5. Почему важно не блокироваться на `ctx.Done()`, если возможна гонка?

🛠 Решение:

🔸 В Go 1.21 есть `context.WithCancelCause`, который позволяет задавать причину отмены.
Но `context.Cause(ctx)` вернёт `nil`, **если ты используешь `context.WithCancel`**, либо, если `ctx.Done()` не был срабатывающим.

🔸 В этом коде `worker(ctx)` запускается и сразу блокируется на:

<-ctx.Done()


Но если отмена происходит **до** того, как `worker` успел начать слушать `ctx.Done()`, и ты используешь старую `WithCancel`, `context.Cause` вернёт `nil`.

🔸 **Правильный способ:**

Убедись, что `context.WithCancelCause` действительно используется и `ctx.Done()` слушается вовремя.

Для Go 1.21+ пример рабочий:



func worker(ctx context.Context) {
for {
select {
case <-ctx.Done():
fmt.Println("Worker stopped:", context.Cause(ctx))
return
case <-time.After(100 * time.Millisecond):
fmt.Println("Working...")
}
}
}



🔸 Альтернатива для старых версий Go (<1.21):


ctx, cancel := context.WithCancel(context.Background())
...
fmt.Println("Worker stopped:", ctx.Err()) // вместо Cause


📌 Вывод:
Начиная с Go 1.21, `context.WithCancelCause` даёт более точный контроль за причинами отмены. Но горутины всё равно должны явно проверять `ctx.Done()` через `select`, иначе отмена может пройти незаметно.

BY Go tests


Warning: Undefined variable $i in /var/www/tg-me/post.php on line 283

Share with your friend now:
tg-me.com/golangtests/790

View MORE
Open in Telegram


Go tests Telegram | DID YOU KNOW?

Date: |

Telegram Be The Next Best SPAC

I have no inside knowledge of a potential stock listing of the popular anti-Whatsapp messaging app, Telegram. But I know this much, judging by most people I talk to, especially crypto investors, if Telegram ever went public, people would gobble it up. I know I would. I’m waiting for it. So is Sergei Sergienko, who claims he owns $800,000 of Telegram’s pre-initial coin offering (ICO) tokens. “If Telegram does a SPAC IPO, there would be demand for this issue. It would probably outstrip the interest we saw during the ICO. Why? Because as of right now Telegram looks like a liberal application that can accept anyone - right after WhatsApp and others have turn on the censorship,” he says.

Newly uncovered hack campaign in Telegram

The campaign, which security firm Check Point has named Rampant Kitten, comprises two main components, one for Windows and the other for Android. Rampant Kitten’s objective is to steal Telegram messages, passwords, and two-factor authentication codes sent by SMS and then also take screenshots and record sounds within earshot of an infected phone, the researchers said in a post published on Friday.

Go tests from ua


Telegram Go tests
FROM USA